<?php

namespace App\Http\Controllers\Finance;

use App\Common\SDK\Facade\FenZhangTong;
use App\Exports\AgentRechargeRecordExport;
use App\Exports\TransferRecordExport;
use App\Http\Controllers\Controller;
use App\Models\AgentTopUpOrder;
use App\Models\Base;
use App\Models\FinanceSupplier;
use App\Models\FinanceTransferRecord;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class FinanceController extends Controller
{
    /**
     * 代理商充值记录
     * @param Request $request
     * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function rechargeRecord(Request $request)
    {
        if ($request->has('export')) {
            return (new AgentRechargeRecordExport($request))->download(sprintf('代理充值记录(%s).xls', Carbon::now()->format('YmdHisu')));
        }

        return $this->response->array(
            AgentTopUpOrder::query()
                ->with(['agent' => function ($builder) {
                    $builder->with(['directInviter', 'indirectInviter', 'affiliatedPartner']);
                }, 'paymentOrders'])
                ->when($request->get('name') || $request->get('phone') || $request->get('level'), function (Builder $builder) use ($request) {
                    $builder
                        ->join('agents', 'agents.id', '=', 'agent_top_up_orders.agent_id')
                        ->when($request->get('name'), function (Builder $builder, $name) {
                            $builder->where('agents.name', 'like', "%$name%");
                        })
                        ->when($request->get('phone'), function (Builder $builder, $phone) {
                            $builder->where('agents.phone', 'like', "%$phone%");
                        })
                        ->when($request->get('level'), function (Builder $builder, $level) {
                            $builder->where('agents.level', $level);
                        });
                })
                ->when($request->get('status'), function (Builder $builder, $status) {
                    $builder->where('agent_top_up_orders.status', $status);
                })
                ->when($request->get('created_at_begin'), function (Builder $builder, $createdAtBegin) {
                    $builder->where('agent_top_up_orders.created_at', '>=', $createdAtBegin);
                })
                ->when($request->get('created_at_end'), function (Builder $builder, $createdAtEnd) {
                    $builder->where('agent_top_up_orders.created_at', '<=', Carbon::parse($createdAtEnd)->endOfDay());
                })
                ->select(['agent_top_up_orders.*'])
                ->paginate()
        );
    }

    /**
     * 转账记录
     * @param Request $request
     */
    public function transferRecord(Request $request)
    {
        if ($request->has('export')) {
            return (new TransferRecordExport($request))->download(sprintf('转账记录(%s).xls', Carbon::now()->format('YmdHisu')));
        }

        return $this->response->array(
            FinanceTransferRecord::query()
                ->with(['subject'])
                ->when($request->get('name'), function (Builder $builder, $name) {
                    $builder
                        ->join('finance_suppliers', 'finance_suppliers.id', '=', 'finance_transfer_records.subject_id')
                        ->where('finance_suppliers.name', 'like', "%$name%");
                })
                ->when($request->get('order_id'), function (Builder $builder, $orderId) {
                    $builder->where('finance_transfer_records.order_id', 'like', "%$orderId%");
                })
                ->when($request->get('status'), function (Builder $builder, $status) {
                    $builder->where('finance_transfer_records.status', $status);
                })
                ->when($request->get('created_at_begin'), function (Builder $builder, $createdAtBegin) {
                    $builder->where('finance_transfer_records.created_at', '>=', $createdAtBegin);
                })
                ->when($request->get('created_at_end'), function (Builder $builder, $createdAtEnd) {
                    $builder->where('finance_transfer_records.created_at', '<=', Carbon::parse($createdAtEnd)->endOfDay());
                })
                ->select(['finance_transfer_records.*'])
                ->paginate()
        );
    }

    /**
     * 转账
     * @param Request $request
     */
    public function transfer(Request $request)
    {
        $reqData = $this->validate($request, [
            'target_type' => 'required|in:' . implode(',', [FinanceTransferRecord::TARGET_TYPE_GENERALLY_FOR_PUBLIC_HOUSEHOLDS, FinanceTransferRecord::TARGET_TYPE_SUPPLIER]),
            'amount' => 'required_if:target_type,1|integer|min:100',
            'amounts' => 'required_if:target_type,2|array',
            'amounts.*.amount' => 'required_if:target_type,2|integer|min:100',
            'amounts.*.id' => ['required_if:target_type,2', Rule::exists('finance_suppliers', 'id')->where('status', FinanceSupplier::STATUS_NORMAL)],
        ], [
            'target_type.required' => '请选择收款方',
            'target_type.in' => '收款方不合法',
            'amount.required_if' => '转账金额不可为空',
            'amount.integer' => '转账金额不合法',
            'amount.min' => '转账金额最少一块钱',
            'amounts.required_if' => '转账金额及对象不可为空',
            'amounts.array' => '转账数据不合法',
            'amounts.*.amount.required_if' => '转账金额不可为空',
            'amounts.*.amount.integer' => '转账金额不合法',
            'amounts.*.amount.min' => '转账金额最少一块钱',
            'amounts.*.id.required_if' => '供应商不可为空',
            'amounts.*.id.exists' => '供应商不合法',
        ]);


        // 一般对公户
        if ($reqData['target_type'] === FinanceTransferRecord::TARGET_TYPE_GENERALLY_FOR_PUBLIC_HOUSEHOLDS) {
            try {
                \DB::beginTransaction();
                // 查询普通资金分户账户余额
                $subAccountFundInquiry = FenZhangTong::subAccountFundInquiry(['acctType' => \App\Common\SDK\Domain\FenZhangTong::SUB_ACCOUNT_TYPE_ORDINARY_CAPITAL_SPLIT]);

                $orderId = 'DG' . Carbon::now()->format('YmdHisu') . Str::random(10);
                FinanceTransferRecord::query()->create([
                    'order_id' => $orderId,
                    'target_type' => $reqData['target_type'],
                    'amount' => $reqData['amount'],
                    'balance' => $subAccountFundInquiry['cashBal'] * Base::CURRENCY_UNIT_CONVERSION,
                    'balance_snapshot' => $subAccountFundInquiry
                ]);

                FenZhangTong::platformWithdrawal([
                    'transAmt' => $reqData['amount'] / 100, // 银行方单价是 元, 后面小数点两位
                    'transId' => $orderId
                ]);

                \DB::commit();
            } catch (\Exception $e) {
                \DB::rollBack();
                \Log::error($e);
                $this->response->errorBadRequest($e->getMessage());
            }

            return $this->response->noContent();
        }

        if ($reqData['target_type'] === FinanceTransferRecord::TARGET_TYPE_SUPPLIER) {
            // 供应商户
            $suppliers = [];
            FinanceSupplier::query()->findOrFail(array_column($reqData['amounts'], 'id'))->each(function ($item) use (&$suppliers) {
                $suppliers[$item['id']] = $item;
            });

            $result = [];
            foreach ($reqData['amounts'] as $item) {
                /** @var FinanceSupplier $supplier */
                $supplier = $suppliers[$item['id']];
                /** @var FinanceTransferRecord $supplierTransferRecord */
                $supplierTransferRecord = null;
                try {
                    // 查询普通资金分户账户余额
                    $subAccountFundInquiry = FenZhangTong::subAccountFundInquiry(['acctType' => \App\Common\SDK\Domain\FenZhangTong::SUB_ACCOUNT_TYPE_ORDINARY_CAPITAL_SPLIT]);
                    $balance = $subAccountFundInquiry['cashBal'] * Base::CURRENCY_UNIT_CONVERSION;
                    if ($balance < $item['amount']) {
                        abort(400, '现金余额不足');
                    }

                    // 供应商转账记录
                    $orderId = 'ZZ' . Carbon::now()->format('YmdHisu') . Str::random(10);
                    $supplierTransferRecord = $supplier->transferRecord()->create([
                        'order_id' => $orderId,
                        'target_type' => FinanceTransferRecord::TARGET_TYPE_SUPPLIER,
                        'amount' => $item['amount'],
                        'balance' => $balance, // 未成功前余额不变
                        'balance_snapshot' => $subAccountFundInquiry,
                    ]);

                    // 资金账户 => 营销费用分户
                    try {
                        FenZhangTong::transferOfPlatformOwnedFunds([
                            'outAcctType' => '01', // 普通资金分户
                            'inAcctType' => '04', // 营销费用分户
                            'transAmt' => $item['amount'] / 100, // 银行端单位 元
                        ]);
                    } catch (\Exception $e) {
                        abort(400, sprintf('资金账户转营销费用分户失败(%s)', $e->getMessage()));
                    }
                    // 营销费用分户 => 供应商
                    try {
                        FenZhangTong::transferToMemberAccount([
                            'transId' => $orderId, // 转账延用 订单 ID
                            'acctType' => '04', // 营销费用分户
                            'transAmt' => $item['amount'] / 100,
                            'platCustNo' => $supplier['plat_cust_no']
                        ]);
                    } catch (\Exception $e) {
                        abort(400, sprintf('营销费用分户转供应商失败(%s)', $e->getMessage()));
                    }

                    $result[] = [
                        'account' => sprintf('%s(%s)', $supplier['name'], $supplier['bank_card_no']),
                        'status_str' => '操作完成'
                    ];
                    $supplierTransferRecord->update([
                        'status' => FinanceTransferRecord::STATUS_COMPLETE,
                        'balance' => $balance - $item['amount'], // 成功后减余额
                    ]);
                } catch (\Exception $e) {
                    \Log::error($e);
                    $result[] = [
                        'account' => sprintf('供应商:%s(%s)', $supplier['name'], $supplier['bank_card_no']),
                        'status_str' => '操作发生错误',
                        'error_msg' => $e->getMessage()
                    ];
                    $supplierTransferRecord !== null && $supplierTransferRecord->update(['status' => FinanceTransferRecord::STATUS_FAIL, 'reason_for_failure' => $e->getMessage()]);
                }
            }

            return $this->response->array($result);
        }
    }
}
